package com.tbit.uqbike.service.business.impl;

import cn.hutool.http.HttpUtil;
import com.tbit.uqbike.constant.*;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.event.AccountConfigEvent;
import com.tbit.uqbike.object.pojo.AccountConfig;
import com.tbit.uqbike.object.pojo.AccountConfigExt;
import com.tbit.uqbike.object.pojo.AccountSmsModel;
import com.tbit.uqbike.object.pojo.BrandRemoteConfig;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.service.base.RedisService;
import com.tbit.uqbike.service.business.AccountConfigService;
import com.tbit.uqbike.service.business.BrandRemoteConfigService;
import com.tbit.uqbike.service.rpcservice.PurviewService;
import com.tbit.uqbike.webmanager.dao.core.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author chenmengran
 * @Description: 运营区域配置
 * @date 2020\1\4 000411:09
 */
@Service
@Slf4j
public class AccountConfigServiceImpl implements AccountConfigService {

    @Autowired
    private PurviewService purviewService;
    @Autowired
    private AccountConfigDao accountConfigDao;
    @Autowired
    private RedisService redisService;
    @Autowired
    private WeChatOperationConfigurationServiceImpl weChatOperationConfigurationServiceImpl;
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private AccountSmsModelDao accountSmsModelDao;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    private AccountConfigExtDao accountConfigExtDao;
    @Resource
    private BrandRemoteConfigService brandRemoteConfigService;
    @Resource
    private ApplicationEventPublisher eventPublisher;

    @Override
    public void edit(LoginInfo loginInfo, AccountConfig accountConfig) {
        Integer accountId = accountConfig.getAccountId();
        //权限
        if (!purviewService.purviewCheck(loginInfo.id, accountId)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        if (((accountConfig.getWxModelMsg() != null && accountConfig.getWxModelMsg() == 1)
                || (null != accountConfig.getWxZffDeposit() && accountConfig.getWxZffDeposit() == 1)
                || (null != accountConfig.getWxZffMm() && accountConfig.getWxZffMm() == 1)) && null == weChatOperationConfigurationServiceImpl.getByAreaId(accountId)) {
            throw new BaseException(SystemCodeEnum.PASSWORD_FREE_PAY_NOT_CONFIGURED);
        }
        //运营开关关闭
        if (accountConfig.getServiceSwitch() != null && accountConfig.getServiceSwitch() == 1) {
            publishServiceSwitchCloseEvent(accountConfig.getAccountId());
        }
        //获取该品牌的短信配置信息
        Integer brandId = accountDao.getBrandIdByAccountId(accountId, 3);
        validateSmsTemplateIsConfigured(brandId, accountConfig);

        int size = machineDao.selectById(accountId).size();
        if (accountConfig.getVirtualCarNum() != null && accountConfig.getVirtualCarNum() > size) {
            throw new BaseException(SystemCodeEnum.CAR_NUMBER_EXCESSIVE);
        }
        if (accountConfig.getSocLimit() != null && accountConfig.getSocLimitIsValid() != null
                && accountConfig.getSocLimit() > accountConfig.getSocLimitIsValid()) {
            throw new BaseException("换电后的电量需要大于等于可换电的电量值");
        }
        AccountConfig accountConfigInDb = accountConfigDao.getById(accountId);
        if (accountConfigInDb != null) {
            accountConfigDao.update(accountConfig);
            if (!Objects.equals(accountConfig.getSocLimit(), accountConfigInDb.getSocLimit())) {
                //如果修改了换电电量限制，调用运维端接口删除运维人员token
                sentFromMain(accountId);
            }
            /**清除redis数据*/
            redisService.del(RedisConstant.CONFIG_KEY_PREFIX + accountId);
        } else {
            HttpUtil.get(OperaPswConstant.ACCOUNT_OPERA_MAIN_URL + ServiceUrlConstant.MAIN_UPDATE_SOC_LIMIT_NOTICE + "?accountId=" + accountId);
            accountConfigDao.insert(accountConfig);
        }

        List<AccountConfigExt> configs = accountConfigExtDao.selectAccountConfigExtList(accountConfig.getAccountId(), "socPower");

        String val = Optional.ofNullable(accountConfig.getRidingPowerOff()).map(Object::toString).orElse("0");
        if (configs.isEmpty()) {
            AccountConfigExt accountConfigExt = new AccountConfigExt();
            accountConfigExt.setAccountId(accountConfig.getAccountId());
            accountConfigExt.setParamKey("socPower");
            accountConfigExt.setParamValue(val);
            accountConfigExt.setUpdateTime(new Date());
            accountConfigExt.setRemark("修改时新增");
            accountConfigExtDao.addAccountConfigExt(accountConfigExt);
        } else {
            AccountConfigExt accountConfigExt = configs.get(0);
            accountConfigExt.setParamValue(val);
            accountConfigExt.setUpdateTime(new Date());
            accountConfigExtDao.updateAccountConfigExt(accountConfigExt);
            redisService.del(Constants.ACCOUNTCONFIG_KEY_PREFIX + accountConfigExt.getAccountId());
        }
    }

    private void validateSmsTemplateIsConfigured(Integer brandId, AccountConfig accountConfig) {
        if (null != accountConfig.getTimeoutNotice() && accountConfig.getTimeoutNotice() > 0) {
            AccountSmsModel accountSmsModel = accountSmsModelDao.queryById(new AccountSmsModel(brandId, 1));
            BrandRemoteConfig brandRemoteConfig = brandRemoteConfigService
                    .getRemoteConfigByBrandIdAndConfigType(brandId, BrandRemoteConfigConstant.STOP_NOT_RETURNED);
            //兼容优驱API短信
            BrandRemoteConfig smsConfig = brandRemoteConfigService.getRemoteConfigByBrandIdAndConfigType(brandId, BrandRemoteConfigConstant.STOP_NOT_RETURNED);
            /*如果开启了长时间未还车进行短信提醒，判断是否配置好短信模板*/
            if (null == accountSmsModel && brandRemoteConfig == null && smsConfig == null) {
                throw new BaseException(SystemCodeEnum.TIMEOUTNOTICE_NOT_DEPLOY);
            }
        }
        if (null != accountConfig.getNotPayNotice() && accountConfig.getNotPayNotice().equals(1)) {
            AccountSmsModel accountSmsModel = accountSmsModelDao.queryById(new AccountSmsModel(brandId, 2));
            BrandRemoteConfig brandRemoteConfig = brandRemoteConfigService
                    .getRemoteConfigByBrandIdAndConfigType(brandId, BrandRemoteConfigConstant.ORDER_NOT_PAID);
            //兼容优驱APi短信
            BrandRemoteConfig smsConfig = brandRemoteConfigService.getRemoteConfigByBrandIdAndConfigType(brandId, BrandRemoteConfigConstant.ORDER_NOT_PAID);
            /*如果开启了订单未支付进行短信提醒，判断是否配置好短信模板*/
            if (null == accountSmsModel && brandRemoteConfig == null && smsConfig == null) {
                throw new BaseException(SystemCodeEnum.NOTPAYNOTICE_NOT_DEPLOY);
            }
        }
    }

    @Override
    public AccountConfig getByAccountId(LoginInfo loginInfo, Integer accountId) {
        if (!purviewService.purviewCheck(loginInfo.id, accountId)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        return accountConfigDao.getById(accountId);
    }

    @Override
    public void insert(AccountConfig accountConfig) {
        sentFromMain(accountConfig.getAccountId());
        accountConfigDao.insert(accountConfig);
    }

    /**
     * 告诉运维端修改了换电电量限制
     *
     * @param accountId 区域id
     */
    void sentFromMain(Integer accountId) {
        threadPoolTaskExecutor.execute(() -> {
            String url = OperaPswConstant.ACCOUNT_OPERA_MAIN_URL + ServiceUrlConstant.MAIN_UPDATE_SOC_LIMIT_NOTICE + "?accountId=" + accountId;
            String res = HttpUtil.get(url);
            log.info("调用url:{},运维端返回:{}", url, res);
        });
    }


    /**
     * 发布运营开关关闭事件
     * @param accountId 区域id
     */
    private void publishServiceSwitchCloseEvent(Integer accountId) {
        if (Objects.nonNull(accountId)) {
            AccountConfigEvent event = new AccountConfigEvent(this, accountId);
            eventPublisher.publishEvent(event);
        }
    }
}
